ποΈGitΠ―ΡΠ°ποΈ
Node / meshtastic / Meshtastic-Android / files / .specify / extensions / review / tests / bats / detect-changed-files.bats
Displaying Raw β’ Download
.specify/extensions/review/tests/bats/detect-changed-files.bats b307ceb5c24b98fa5c8a49fdf95e56eeaa4187bb (b307ceb5) Text, 21.47 KB
Tffa657load Ta5d6ff"Ta5d6fftest_helperTa5d6ff"
Te6edf3setupTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3setup_temp_dir
Tb4b4b4}
Te6edf3teardownTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3teardown_temp_dir
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# 1a. Git Availability Errors
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6fffails when not in a git repositoryTa5d6ff" Tb4b4b4{
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff"
Te6edf3assert_failure
Tb4b4b4[ Ta5d6ff"Ta5d6ff$statusTa5d6ff" Tff7b72-Te6edf3eq T79c0ff1 Tb4b4b4]
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffNot a git repositoryTa5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6fffails with JSON error when not in a git repositoryTa5d6ff" Tb4b4b4{
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_failure
Tb4b4b4[ Ta5d6ff"Ta5d6ff$statusTa5d6ff" Tff7b72-Te6edf3eq T79c0ff1 Tb4b4b4]
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6fferrorTa5d6ff"Ta5d6ff'
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffNot a git repositoryTa5d6ff"
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Help
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ff--help shows usage informationTa5d6ff" Tb4b4b4{
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3help
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffUsageTa5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffdetect-changed-filesTa5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ff-h shows usage informationTa5d6ff" Tb4b4b4{
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Te6edf3h
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffUsageTa5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffunknown option fails with errorTa5d6ff" Tb4b4b4{
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3bogus
Te6edf3assert_failure
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffUnknown optionTa5d6ff"
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# No Changes Detected (exit code 2)
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffexit code 2 when no changes in clean repoTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff"
Tb4b4b4[ Ta5d6ff"Ta5d6ff$statusTa5d6ff" Tff7b72-Te6edf3eq T79c0ff2 Tb4b4b4]
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffNo changes detectedTa5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffexit code 2 with JSON output when no changesTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Tb4b4b4[ Ta5d6ff"Ta5d6ff$statusTa5d6ff" Tff7b72-Te6edf3eq T79c0ff2 Tb4b4b4]
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
Te6edf3local Te6edf3msgTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffmessageTa5d6ff"Tb4b4b4)
Tb4b4b4[Tb4b4b4[ Ta5d6ff"Ta5d6ff$msgTa5d6ff" Tff7b72== Tff7b72*Ta5d6ff"Ta5d6ffNo changes detectedTa5d6ff"Tff7b72* Tb4b4b4]Tb4b4b4]
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Mode B β Working Directory: Unstaged Changes
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffdetects unstaged changes (Mode B)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Create and commit a file, then modify it
Te6edf3echo Ta5d6ff"Ta5d6ffinitialTa5d6ff" Tff7b72> Te6edf3trackedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3trackedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd tracked fileTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffmodifiedTa5d6ff" Tff7b72> Te6edf3trackedTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff"
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6fftracked.txtTa5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffWorking directory changesTa5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffdetects unstaged changes with --json (Mode B)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffinitialTa5d6ff" Tff7b72> Te6edf3trackedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3trackedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd tracked fileTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffmodifiedTa5d6ff" Tff7b72> Te6edf3trackedTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
Te6edf3local Te6edf3modeTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffmodeTa5d6ff"Tb4b4b4)
Tb4b4b4[Tb4b4b4[ Ta5d6ff"Ta5d6ff$modeTa5d6ff" Tff7b72== Ta5d6ff"Ta5d6ffWorking directory changes (staged + unstaged)Ta5d6ff" Tb4b4b4]Tb4b4b4]
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6fftracked.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Mode B β Working Directory: Staged Changes
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffdetects staged changes (Mode B)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffnew fileTa5d6ff" Tff7b72> Te6edf3stagedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3stagedTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff"
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffstaged.txtTa5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffWorking directory changesTa5d6ff"
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Mode B β Staged + Unstaged Deduplication
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffdeduplicates staged and unstaged changes (Mode B)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Create a file, commit, stage a change, then modify again (unstaged)
Te6edf3echo Ta5d6ff"Ta5d6ffv1Ta5d6ff" Tff7b72> Te6edf3bothTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3bothTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd both.txtTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffv2Ta5d6ff" Tff7b72> Te6edf3bothTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3bothTff7b72.Td2a8fftxt
Te6edf3echo Ta5d6ff"Ta5d6ffv3Ta5d6ff" Tff7b72> Te6edf3bothTff7b72.Td2a8fftxt
T8b949e# Also add a new staged-only file
Te6edf3echo Ta5d6ff"Ta5d6ffnewTa5d6ff" Tff7b72> Te6edf3onlyTff7b72-Te6edf3stagedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3onlyTff7b72-Te6edf3stagedTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
T8b949e# both.txt should appear only once
Te6edf3local Te6edf3countTff7b72=Tff7b72$Tb4b4b4(Te6edf3echo Ta5d6ff"Ta5d6ff$outputTa5d6ff" Tff7b72| Te6edf3python3 Tff7b72-Te6edf3c Ta5d6ff"Ta5d6ffimport json,sys; print(json.load(sys.stdin)[Ta5d6ff'Ta5d6ffchanged_filesTa5d6ff'Ta5d6ff].count(Ta5d6ff'Ta5d6ffboth.txtTa5d6ff'Ta5d6ff))Ta5d6ff"Tb4b4b4)
Tb4b4b4[ Ta5d6ff"Ta5d6ff$countTa5d6ff" Tff7b72-Te6edf3eq T79c0ff1 Tb4b4b4]
T8b949e# only-staged.txt should also be present
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffonly-staged.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Mode A β Feature Branch Diff
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffdetects feature branch changes via merge-base (Mode A)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Create a feature branch with a new file
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3featureTff7b72-Te6edf3branch
Te6edf3echo Ta5d6ff"Ta5d6fffeature codeTa5d6ff" Tff7b72> Te6edf3featureTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3featureTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd feature fileTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff"
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6fffeature.txtTa5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffFeature branch diffTa5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffMode A --json has correct structureTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3featureTff7b72-Te6edf3branch
Te6edf3echo Ta5d6ff"Ta5d6fffeature codeTa5d6ff" Tff7b72> Te6edf3featureTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3featureTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd feature fileTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
Te6edf3local Te6edf3branchTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffbranchTa5d6ff"Tb4b4b4)
Tb4b4b4[ Ta5d6ff"Ta5d6ff$branchTa5d6ff" Tff7b72= Ta5d6ff"Ta5d6fffeature-branchTa5d6ff" Tb4b4b4]
Te6edf3local Te6edf3modeTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffmodeTa5d6ff"Tb4b4b4)
Tb4b4b4[Tb4b4b4[ Ta5d6ff"Ta5d6ff$modeTa5d6ff" Tff7b72== Ta5d6ff"Ta5d6ffFeature branch diffTa5d6ff"Tff7b72* Tb4b4b4]Tb4b4b4]
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6fffeature.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffMode A excludes deleted files (diff-filter=ACMR)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Add a file on main and push
Te6edf3echo Ta5d6ff"Ta5d6ffto deleteTa5d6ff" Tff7b72> Te6edf3deleteTff7b72-Te6edf3meTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3deleteTff7b72-Te6edf3meTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd file to deleteTa5d6ff"
Te6edf3git Te6edf3push Tff7b72-Tff7b72-Te6edf3quiet Te6edf3origin Te6edf3main
T8b949e# Create feature branch, delete the file, add another
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3featureTff7b72-Te6edf3delete
Te6edf3git Te6edf3rm Tff7b72-Tff7b72-Te6edf3quiet Te6edf3deleteTff7b72-Te6edf3meTff7b72.Td2a8fftxt
Te6edf3echo Ta5d6ff"Ta5d6ffkeep meTa5d6ff" Tff7b72> Te6edf3keepTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3keepTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffDelete and addTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
T8b949e# delete-me.txt should NOT appear (it was deleted)
Te6edf3local Te6edf3filesTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_array_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffchanged_filesTa5d6ff"Tb4b4b4)
Tff7b72! Te6edf3echo Ta5d6ff"Ta5d6ff$filesTa5d6ff" Tff7b72| Te6edf3grep Tff7b72-Te6edf3q Ta5d6ff"Ta5d6ffdelete-me.txtTa5d6ff"
T8b949e# keep.txt should appear
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffkeep.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffMode A detects multiple changed filesTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3multiTff7b72-Te6edf3files
Te6edf3echo Ta5d6ff"Ta5d6ffaTa5d6ff" Tff7b72> Te6edf3fileTff7b72-Te6edf3aTff7b72.Td2a8fftxt
Te6edf3echo Ta5d6ff"Ta5d6ffbTa5d6ff" Tff7b72> Te6edf3fileTff7b72-Te6edf3bTff7b72.Td2a8fftxt
Te6edf3mkdir Tff7b72-Te6edf3p Te6edf3sub
Te6edf3echo Ta5d6ff"Ta5d6ffcTa5d6ff" Tff7b72> Te6edf3subTff7b72/Te6edf3fileTff7b72-Te6edf3cTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Tff7b72.
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd multiple filesTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6fffile-a.txtTa5d6ff"Ta5d6ff'
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6fffile-b.txtTa5d6ff"Ta5d6ff'
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffsub/file-c.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Mode A β Feature Branch + Uncommitted Changes
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffMode A includes staged uncommitted filesTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3featureTff7b72-Te6edf3staged
Te6edf3echo Ta5d6ff"Ta5d6ffcommittedTa5d6ff" Tff7b72> Te6edf3committedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3committedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd committed fileTa5d6ff"
T8b949e# Stage a new file without committing
Te6edf3echo Ta5d6ff"Ta5d6ffstagedTa5d6ff" Tff7b72> Te6edf3stagedTff7b72-Te6edf3onlyTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3stagedTff7b72-Te6edf3onlyTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
T8b949e# Both committed and staged files should appear
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffcommitted.txtTa5d6ff"Ta5d6ff'
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffstaged-only.txtTa5d6ff"Ta5d6ff'
Te6edf3local Te6edf3modeTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffmodeTa5d6ff"Tb4b4b4)
Tb4b4b4[Tb4b4b4[ Ta5d6ff"Ta5d6ff$modeTa5d6ff" Tff7b72== Tff7b72*Ta5d6ff"Ta5d6ffuncommittedTa5d6ff"Tff7b72* Tb4b4b4]Tb4b4b4]
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffMode A includes unstaged uncommitted filesTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Create a file on main, push it, then modify on feature branch
Te6edf3echo Ta5d6ff"Ta5d6fforiginalTa5d6ff" Tff7b72> Te6edf3existingTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3existingTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd existing fileTa5d6ff"
Te6edf3git Te6edf3push Tff7b72-Tff7b72-Te6edf3quiet Te6edf3origin Te6edf3main
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3featureTff7b72-Te6edf3unstaged
Te6edf3echo Ta5d6ff"Ta5d6ffcommitted on branchTa5d6ff" Tff7b72> Te6edf3committedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3committedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd committed fileTa5d6ff"
T8b949e# Modify existing file without staging
Te6edf3echo Ta5d6ff"Ta5d6ffmodifiedTa5d6ff" Tff7b72> Te6edf3existingTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
T8b949e# Both committed diff and unstaged modification should appear
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffcommitted.txtTa5d6ff"Ta5d6ff'
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffexisting.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffMode A deduplicates committed and uncommitted filesTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3featureTff7b72-Te6edf3dedup
Te6edf3echo Ta5d6ff"Ta5d6ffv1Ta5d6ff" Tff7b72> Te6edf3sharedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3sharedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd shared fileTa5d6ff"
T8b949e# Modify the same file (unstaged) β it appears in both committed diff and unstaged
Te6edf3echo Ta5d6ff"Ta5d6ffv2Ta5d6ff" Tff7b72> Te6edf3sharedTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
T8b949e# shared.txt should appear exactly once
Te6edf3local Te6edf3countTff7b72=Tff7b72$Tb4b4b4(Te6edf3echo Ta5d6ff"Ta5d6ff$outputTa5d6ff" Tff7b72| Te6edf3python3 Tff7b72-Te6edf3c Ta5d6ff"Ta5d6ffimport json,sys; print(json.load(sys.stdin)[Ta5d6ff'Ta5d6ffchanged_filesTa5d6ff'Ta5d6ff].count(Ta5d6ff'Ta5d6ffshared.txtTa5d6ff'Ta5d6ff))Ta5d6ff"Tb4b4b4)
Tb4b4b4[ Ta5d6ff"Ta5d6ff$countTa5d6ff" Tff7b72-Te6edf3eq T79c0ff1 Tb4b4b4]
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Default Branch Detection Fallbacks
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffdetects origin/main as default branchTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Unset symbolic-ref to force fallback
Te6edf3git Tff7b72remote Te6edf3setTff7b72-Te6edf3head Te6edf3origin Tff7b72-Tff7b72-Te6edf3delete T79c0ff2Tff7b72>Tff7b72/Te6edf3devTff7b72/Tffa657null Tff7b72|| Tff7b72true
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3testTff7b72-Te6edf3branch
Te6edf3echo Ta5d6ff"Ta5d6fftestTa5d6ff" Tff7b72> Te6edf3testTff7b72-Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3testTff7b72-Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd test fileTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3local Te6edf3defaultTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffdefault_branchTa5d6ff"Tb4b4b4)
Tb4b4b4[ Ta5d6ff"Ta5d6ff$defaultTa5d6ff" Tff7b72= Ta5d6ff"Ta5d6ffmainTa5d6ff" Tb4b4b4]
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffdetects origin/master as default branch when no origin/mainTa5d6ff" Tb4b4b4{
T8b949e# Create a bare repo with master as default
Te6edf3local Te6edf3bareTff7b72=Ta5d6ff"Ta5d6ff${TEST_TEMP_DIR}/_bare_masterTa5d6ff"
Te6edf3mkdir Tff7b72-Te6edf3p Ta5d6ff"Ta5d6ff$bareTa5d6ff"
Te6edf3git Tff7b72-Te6edf3C Ta5d6ff"Ta5d6ff$bareTa5d6ff" Te6edf3init Tff7b72-Tff7b72-Te6edf3bare Tff7b72-Tff7b72-Te6edf3quiet
Te6edf3git Tff7b72-Te6edf3C Ta5d6ff"Ta5d6ff$bareTa5d6ff" Te6edf3symbolicTff7b72-Te6edf3ref Te6edf3HEAD Te6edf3refsTff7b72/Te6edf3headsTff7b72/Tff7b72master
T8b949e# Clone-like setup
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3git Te6edf3init Tff7b72-Tff7b72-Te6edf3quiet
Te6edf3git Te6edf3config Te6edf3userTff7b72.Td2a8ffemail Ta5d6ff"Ta5d6fftest@example.comTa5d6ff"
Te6edf3git Te6edf3config Te6edf3userTff7b72.Td2a8ffname Ta5d6ff"Ta5d6ffTestTa5d6ff"
Te6edf3git Tff7b72remote Te6edf3add Te6edf3origin Ta5d6ff"Ta5d6ff$bareTa5d6ff"
T8b949e# Create initial commit on master and push
Te6edf3touch Tff7b72.Td2a8ffgitkeep
Te6edf3git Te6edf3add Tff7b72.
Te6edf3git Te6edf3checkout Tff7b72-Te6edf3b Tff7b72master Tff7b72-Tff7b72-Te6edf3quiet T79c0ff2Tff7b72>Tff7b72/Te6edf3devTff7b72/Tffa657null Tff7b72|| Tff7b72true
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffInitial commitTa5d6ff"
Te6edf3git Te6edf3push Tff7b72-Tff7b72-Te6edf3quiet Te6edf3origin Tff7b72master
T8b949e# Remove symbolic-ref to force fallback
Te6edf3git Tff7b72remote Te6edf3setTff7b72-Te6edf3head Te6edf3origin Tff7b72-Tff7b72-Te6edf3delete T79c0ff2Tff7b72>Tff7b72/Te6edf3devTff7b72/Tffa657null Tff7b72|| Tff7b72true
T8b949e# Create feature branch
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3testTff7b72-Te6edf3branch
Te6edf3echo Ta5d6ff"Ta5d6fftestTa5d6ff" Tff7b72> Te6edf3testTff7b72-Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3testTff7b72-Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd test fileTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3local Te6edf3defaultTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffdefault_branchTa5d6ff"Tb4b4b4)
Tb4b4b4[ Ta5d6ff"Ta5d6ff$defaultTa5d6ff" Tff7b72= Ta5d6ff"Ta5d6ffmasterTa5d6ff" Tb4b4b4]
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6fffalls back to Mode B when no remote default branch foundTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# No remote configured, so no origin/* branches
Te6edf3echo Ta5d6ff"Ta5d6ffchangeTa5d6ff" Tff7b72> Te6edf3newTff7b72-Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3newTff7b72-Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3local Te6edf3modeTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffmodeTa5d6ff"Tb4b4b4)
Tb4b4b4[Tb4b4b4[ Ta5d6ff"Ta5d6ff$modeTa5d6ff" Tff7b72== Ta5d6ff"Ta5d6ffWorking directory changesTa5d6ff"Tff7b72* Tb4b4b4]Tb4b4b4]
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Detached HEAD
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffdetached HEAD falls back to Mode BTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Create a commit and detach HEAD
Te6edf3echo Ta5d6ff"Ta5d6fffileTa5d6ff" Tff7b72> Te6edf3detachedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3detachedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd fileTa5d6ff"
Te6edf3local Te6edf3commit_hashTff7b72=Tff7b72$Tb4b4b4(Te6edf3git Te6edf3revTff7b72-Te6edf3parse Te6edf3HEADTb4b4b4)
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Ta5d6ff"Ta5d6ff$commit_hashTa5d6ff"
T8b949e# Make a change
Te6edf3echo Ta5d6ff"Ta5d6ffmodifiedTa5d6ff" Tff7b72> Te6edf3detachedTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff"
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffWorking directory changesTa5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffdetached.txtTa5d6ff"
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# JSON Output Validation
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ff--json output is valid JSON with all required keysTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffcontentTa5d6ff" Tff7b72> Te6edf3newTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3newTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
T8b949e# Verify all expected keys exist
Te6edf3echo Ta5d6ff"Ta5d6ff$outputTa5d6ff" Tff7b72| Te6edf3python3 Tff7b72-Te6edf3c Ta5d6ff"
Te6edf3import Te6edf3jsonTb4b4b4, Te6edf3sys
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadTb4b4b4(Te6edf3sysTff7b72.Td2a8ffstdinTb4b4b4)
Tffa657assert Ta5d6ff'Ta5d6ffbranchTa5d6ff' Tff7b72in Te6edf3dataTb4b4b4, Ta5d6ff'Ta5d6ffmissing branch keyTa5d6ff'
Tffa657assert Ta5d6ff'Ta5d6ffdefault_branchTa5d6ff' Tff7b72in Te6edf3dataTb4b4b4, Ta5d6ff'Ta5d6ffmissing default_branch keyTa5d6ff'
Tffa657assert Ta5d6ff'Ta5d6ffmodeTa5d6ff' Tff7b72in Te6edf3dataTb4b4b4, Ta5d6ff'Ta5d6ffmissing mode keyTa5d6ff'
Tffa657assert Ta5d6ff'Ta5d6ffchanged_filesTa5d6ff' Tff7b72in Te6edf3dataTb4b4b4, Ta5d6ff'Ta5d6ffmissing changed_files keyTa5d6ff'
Tffa657assert Te6edf3isinstanceTb4b4b4(Te6edf3dataTb4b4b4[Ta5d6ff'Ta5d6ffchanged_filesTa5d6ff'Tb4b4b4]Tb4b4b4, Te6edf3listTb4b4b4)Tb4b4b4, Ta5d6ff'Ta5d6ffchanged_files should be a listTa5d6ff'
Tffa657printTb4b4b4(Ta5d6ff'Ta5d6ffAll keys present and correct typesTa5d6ff'Tb4b4b4)
Ta5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6fftext mode output has correct formatTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffcontentTa5d6ff" Tff7b72> Te6edf3formattedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3formattedTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff"
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffBRANCH:Ta5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffDEFAULT_BRANCH:Ta5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffMODE:Ta5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffCHANGED_FILES:Ta5d6ff"
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6ffformatted.txtTa5d6ff"
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Edge Cases
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffhandles files with spaces in namesTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffcontentTa5d6ff" Tff7b72> Ta5d6ff"Ta5d6fffile with spaces.txtTa5d6ff"
Te6edf3git Te6edf3add Ta5d6ff"Ta5d6fffile with spaces.txtTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff"
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff"Ta5d6fffile with spaces.txtTa5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffhandles nested directory changesTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3mkdir Tff7b72-Te6edf3p Te6edf3deepTff7b72/Te6edf3nestedTff7b72/Te6edf3path
Te6edf3echo Ta5d6ff"Ta5d6ffdeepTa5d6ff" Tff7b72> Te6edf3deepTff7b72/Te6edf3nestedTff7b72/Te6edf3pathTff7b72/Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Tff7b72.
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffdeep/nested/path/file.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffonly reports ACMR files (Added, Copied, Modified, Renamed)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Add and commit files
Te6edf3echo Ta5d6ff"Ta5d6ffkeepTa5d6ff" Tff7b72> Te6edf3keepTff7b72.Td2a8fftxt
Te6edf3echo Ta5d6ff"Ta5d6ffremoveTa5d6ff" Tff7b72> Te6edf3removeTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Tff7b72.
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd filesTa5d6ff"
T8b949e# Delete one, modify another β only staged
Te6edf3git Te6edf3rm Tff7b72-Tff7b72-Te6edf3quiet Te6edf3removeTff7b72.Td2a8fftxt
Te6edf3echo Ta5d6ff"Ta5d6ffmodifiedTa5d6ff" Tff7b72> Te6edf3keepTff7b72.Td2a8fftxt
Te6edf3echo Ta5d6ff"Ta5d6ffaddedTa5d6ff" Tff7b72> Te6edf3addedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Tff7b72.
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
T8b949e# keep.txt (Modified) and added.txt (Added) should be present
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffkeep.txtTa5d6ff"Ta5d6ff'
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffadded.txtTa5d6ff"Ta5d6ff'
T8b949e# remove.txt (Deleted) should NOT be present
Te6edf3local Te6edf3filesTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_array_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffchanged_filesTa5d6ff"Tb4b4b4)
Tb4b4b4[Tb4b4b4[ Tff7b72! Ta5d6ff"Ta5d6ff$filesTa5d6ff" Tff7b72== Tff7b72*Ta5d6ff"Ta5d6ffremove.txtTa5d6ff"Tff7b72* Tb4b4b4]Tb4b4b4]
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffMode A: branch field matches current branch nameTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3myTff7b72-Te6edf3featureTff7b72-T79c0ff123
Te6edf3echo Ta5d6ff"Ta5d6ffxTa5d6ff" Tff7b72> Te6edf3xTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3xTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffcommitTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3local Te6edf3branchTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffbranchTa5d6ff"Tb4b4b4)
Tb4b4b4[ Ta5d6ff"Ta5d6ff$branchTa5d6ff" Tff7b72= Ta5d6ff"Ta5d6ffmy-feature-123Ta5d6ff" Tb4b4b4]
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffMode B: branch field shows current branch on defaultTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffchangeTa5d6ff" Tff7b72> Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3fileTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
T8b949e# Branch should be main (or master depending on git default)
Te6edf3local Te6edf3branchTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffbranchTa5d6ff"Tb4b4b4)
Tb4b4b4[Tb4b4b4[ Ta5d6ff"Ta5d6ff$branchTa5d6ff" Tff7b72== Ta5d6ff"Ta5d6ffmainTa5d6ff" Tff7b72|| Ta5d6ff"Ta5d6ff$branchTa5d6ff" Tff7b72== Ta5d6ff"Ta5d6ffmasterTa5d6ff" Tb4b4b4]Tb4b4b4]
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Special Characters in Filenames
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffhandles filenames with double quotes in JSON modeTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Create a file with a double quote in its name
Te6edf3local Te6edf3fnameTff7b72=Ta5d6ff'Ta5d6fffileTa5d6ff"Ta5d6ffquote.txtTa5d6ff'
Te6edf3echo Ta5d6ff"Ta5d6ffcontentTa5d6ff" Tff7b72> Ta5d6ff"Ta5d6ff$fnameTa5d6ff"
Te6edf3git Te6edf3add Ta5d6ff"Ta5d6ff$fnameTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
T8b949e# The filename should be properly escaped in JSON
Te6edf3local Te6edf3filesTff7b72=Tff7b72$Tb4b4b4(Te6edf3json_array_field Ta5d6ff"Ta5d6ff$outputTa5d6ff" Ta5d6ff"Ta5d6ffchanged_filesTa5d6ff"Tb4b4b4)
Tb4b4b4[Tb4b4b4[ Ta5d6ff"Ta5d6ff$filesTa5d6ff" Tff7b72== Tff7b72*Ta5d6ff'Ta5d6fffileTa5d6ff"Ta5d6ffquote.txtTa5d6ff'Tff7b72* Tb4b4b4]Tb4b4b4]
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffhandles filenames with backslashes in JSON modeTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Create a file with a backslash in its name
Te6edf3local Te6edf3fnameTff7b72=Ta5d6ff'Ta5d6fffileTa5d6ff\Ta5d6ffslash.txtTa5d6ff'
Te6edf3echo Ta5d6ff"Ta5d6ffcontentTa5d6ff" Tff7b72> Ta5d6ff"Ta5d6ff$fnameTa5d6ff"
Te6edf3git Te6edf3add Ta5d6ff"Ta5d6ff$fnameTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffhandles filenames with special characters in JSON modeTa5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
T8b949e# Create files with various special characters
Te6edf3echo Ta5d6ff"Ta5d6ffaTa5d6ff" Tff7b72> Ta5d6ff"Ta5d6fffile (1).txtTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffbTa5d6ff" Tff7b72> Ta5d6ff"Ta5d6fffileTa5d6ff'Ta5d6ffs.txtTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffcTa5d6ff" Tff7b72> Ta5d6ff"Ta5d6fffile&more.txtTa5d6ff"
Te6edf3git Te6edf3add Tff7b72.
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_valid_json Ta5d6ff"Ta5d6ff$outputTa5d6ff"
T8b949e# All three files should be present
Te6edf3local Te6edf3countTff7b72=Tff7b72$Tb4b4b4(Te6edf3echo Ta5d6ff"Ta5d6ff$outputTa5d6ff" Tff7b72| Te6edf3python3 Tff7b72-Te6edf3c Ta5d6ff"Ta5d6ffimport json,sys; print(len(json.load(sys.stdin)[Ta5d6ff'Ta5d6ffchanged_filesTa5d6ff'Ta5d6ff]))Ta5d6ff"Tb4b4b4)
Tb4b4b4[ Ta5d6ff"Ta5d6ff$countTa5d6ff" Tff7b72-Te6edf3eq T79c0ff3 Tb4b4b4]
Tb4b4b4}
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
T8b949e# Renamed Files
T8b949e# ββββββββββββββββββββββββββββββββββββββββββββββ
@Te6edf3test Ta5d6ff"Ta5d6ffMode A detects renamed files (diff-filter includes R)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo_with_remote Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffcontentTa5d6ff" Tff7b72> Te6edf3originalTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3originalTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd originalTa5d6ff"
Te6edf3git Te6edf3push Tff7b72-Tff7b72-Te6edf3quiet Te6edf3origin Te6edf3main
Te6edf3git Te6edf3checkout Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3b Te6edf3featureTff7b72-Te6edf3rename
Te6edf3git Te6edf3mv Te6edf3originalTff7b72.Td2a8fftxt Te6edf3renamedTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffRename fileTa5d6ff"
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffrenamed.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
@Te6edf3test Ta5d6ff"Ta5d6ffMode B detects renamed files (staged)Ta5d6ff" Tb4b4b4{
Te6edf3init_git_repo Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3cd Ta5d6ff"Ta5d6ff$TEST_TEMP_DIRTa5d6ff"
Te6edf3echo Ta5d6ff"Ta5d6ffcontentTa5d6ff" Tff7b72> Te6edf3originalTff7b72.Td2a8fftxt
Te6edf3git Te6edf3add Te6edf3originalTff7b72.Td2a8fftxt
Te6edf3git Te6edf3commit Tff7b72-Tff7b72-Te6edf3quiet Tff7b72-Te6edf3m Ta5d6ff"Ta5d6ffAdd originalTa5d6ff"
Te6edf3git Te6edf3mv Te6edf3originalTff7b72.Td2a8fftxt Te6edf3renamedTff7b72.Td2a8fftxt
Te6edf3run Te6edf3bash Ta5d6ff"Ta5d6ff$SCRIPTS_DIR/detect-changed-files.shTa5d6ff" Tff7b72-Tff7b72-Te6edf3json
Te6edf3assert_success
Te6edf3assert_output Tff7b72-Tff7b72-Te6edf3partial Ta5d6ff'Ta5d6ff"Ta5d6ffrenamed.txtTa5d6ff"Ta5d6ff'
Tb4b4b4}
Served by rngit 1.5.4 - Generated in 0.14s